package org.xqh.utils;

import lombok.extern.slf4j.Slf4j;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @ClassName IPUtils
 * @Description TODO
 * @Author xuqianghui
 * @Date 2024/4/9 21:50
 * @Version 1.0
 */
@Slf4j
public class IPUtils {


    /**
     * 根据Internet Assigned Numbers Authority (IANA)的规定，私有IP地址范围包括：
     * 10.0.0.0/8：范围从 10.0.0.0 到 10.255.255.255
     * 172.16.0.0/12：范围从 172.16.0.0 到 172.31.255.255
     * 192.168.0.0/16：范围从 192.168.0.0 到 192.168.255.255
     * @param ipAddress
     * @return
     */
    public static boolean isLocalIpAddress(String ipAddress) {
        InetAddress inetAddress = null;
        try {
            inetAddress = InetAddress.getByName(ipAddress);
        } catch (UnknownHostException e) {
            log.error("", e);
            return false;
        }
        byte[] bytes = inetAddress.getAddress();

        // Check for IPv4 addresses
        if (bytes.length == 4) {
            int firstOctet = bytes[0] & 0xFF;
            // Check for reserved LAN ranges
            if ((firstOctet == 10 || (firstOctet == 172 && (bytes[1] & 0xFF) >= 16 && (bytes[1] & 0xFF) <= 31) || (firstOctet == 192 && bytes[1] == (byte) 168))) {
                return true;
            }
        }

        // If not an IPv4 address or not within the reserved LAN ranges, consider it non-local
        return false;
    }

    public static boolean isLocalIPv6Address(String ipv6Address) throws UnknownHostException {
        Inet6Address inet6Address = (Inet6Address) InetAddress.getByName(ipv6Address);
        byte[] addressBytes = inet6Address.getAddress();
        int prefix = inet6Address.getScopeId(); // May be useful for additional checks but not necessary for basic ULA detection

        // Check if the address starts with the fd00::/8 prefix
        if ((addressBytes[0] & 0xFF) == 0xfd) {
            return true;
        }

        // Address does not fall within the ULA range
        return false;
    }

    public static void main(String[] args) throws UnknownHostException {
//        checkIpAddress("10.255.33.12");
//        checkIpAddress("10.0.33.12");
        checkIpAddress("10.0.244.222");
        checkIpAddress("11.15.33.12");
        checkIpAddress("9.168.33.12");

        checkIpAddress("172.16.244.222");
        checkIpAddress("172.15.33.12");
        checkIpAddress("172.17.33.12");
        checkIpAddress("172.31.33.12");
        checkIpAddress("172.32.33.12");

        checkIpAddress("192.168.244.222");
        checkIpAddress("192.167.15.33");
        checkIpAddress("192.169.168.33");
    }

    public static void checkIpAddress(String ip){
        System.out.println(ip + "是否局域网IP: " + isLocalIpAddress(ip));
//        System.out.println(ip + "是否外网IP: " + isPublicIPv4Address(ip));
    }

    public static boolean isPublicIPv4Address(String ipAddress) {
        InetAddress inetAddress = null;
        try {
            inetAddress = InetAddress.getByName(ipAddress);
        } catch (UnknownHostException e) {
            log.error("", e);
            return false;
        }
        byte[] bytes = inetAddress.getAddress();

        // Check for IPv4 addresses
        if (bytes.length == 4) {
            int firstOctet = bytes[0] & 0xFF;
            if ((firstOctet >= 10 && firstOctet <= 100) || firstOctet == 172 || firstOctet == 192) {
                // Check for reserved LAN ranges
                if ((firstOctet == 10 || (firstOctet == 172 && (bytes[1] & 0xFF) >= 16 && (bytes[1] & 0xFF) <= 31) || (firstOctet == 192 && bytes[1] == (byte) 168))) {
                    return false;
                }
            }
        }

        // If not an IPv4 address or not within the reserved LAN ranges, consider it non-local
        return true;
    }

}
